home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1996 #1 / Amiga Plus CD - 1996 - No. 1.iso / pd / netz / xbtx_v1.1 / ioserial.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-26  |  11.8 KB  |  623 lines

  1. /*
  2. **    $Id: IOSerial.cpp 1.3 1995/09/26 16:48:58 olsen Exp olsen $
  3. **
  4. **    :ts=4
  5. */
  6.  
  7. /*
  8.  * Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
  9.  *
  10.  * Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
  11.  * Erlangen-Nuremberg, Germany.
  12.  * All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that the following conditions
  16.  * are met:
  17.  * 1. Redistributions of source code must retain the above copyright
  18.  *    notice, this list of conditions and the following disclaimer.
  19.  * 2. Redistributions in binary form must reproduce the above copyright
  20.  *    notice, this list of conditions and the following disclaimer in the
  21.  *    documentation and/or other materials provided with the distribution.
  22.  * 3. All advertising materials mentioning features or use of this software
  23.  *    must display the following acknowledgement:
  24.  *    This product includes software developed by the University of
  25.  *    Erlangen-Nuremberg, Germany.
  26.  * 4. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  31.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  32.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
  33.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  36.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  37.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  38.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  39.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40.  *
  41.  * This software has not been validated by the ``Bundesamt fuer Zulassungen in
  42.  * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
  43.  * must not be used for accessing the BTX-Network of the Telekom in Germany.
  44.  *
  45.  * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
  46.  * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
  47.  * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
  48.  */
  49.  
  50. #include "IOSerial.hpp"
  51. #include "Control.h"
  52. #include "RawKeys.h"
  53. #include <string.h>
  54. #include <stdio.h>
  55.  
  56. #define log(x)    ;
  57.  
  58. /********************  This is CONTROL SET C0 of CEPT ***********************/
  59.  
  60. #define NOBLOCK    0    /* not receiving a block */
  61. #define TEXTBLOCK  1    /* normal text block     */
  62. #define IMAGEBLOCK 2    /* transparent block     */
  63. #define ERROR       0    /* status error          */
  64.  
  65. #define NUL 0x00         /* Null                     (data link) */
  66. #define SOH 0x01         /* start of heading         (data link) */
  67. #define STX 0x02         /* start text                 (data link) */
  68. #define ETX 0x03         /* end text                 (data link) */
  69. #define EOT 0x04         /* end of transmission      (data link) */
  70. #define ENQ 0x05         /* enquiry                  (data link) */
  71. #define ACK 0x06         /* acknowledge              (data link) */
  72. #define ITB 0x07         /* end intermediate block     (data link) */
  73. #define APB 0x08         /* active position back     (control sequence) */
  74. #define APF 0x09         /* active position forward  (control sequence) */
  75. #define APD 0x0a         /* active position down     (control sequence) */
  76. #define APU 0x0b         /* active position up         (control sequence) */
  77. #define CS    0x0c         /* clear screen             (control sequence) */
  78. #define APR 0x0d         /* active position return     (control sequence) */
  79. #define LS1 0x0e         /* locking shift 1          (control sequence) */
  80. #define LS0 0x0f         /* locking shift 0          (control sequence) */
  81. #define DLE 0x10         /* data link escape         (data link) */
  82. #define CON 0x11         /* cursor on                 (control sequence) */
  83. #define RPT 0x12         /* repeat last character     (control sequence) */
  84. #define INI 0x13         /* initiator '*'             (btx special) */
  85. #define COF 0x14         /* cursor off                 (control sequence) */
  86. #define NAK 0x15         /* negative acknowledge     (data link) */
  87. #define SYN 0x16         /*                          (data link) */
  88. #define ETB 0x17         /* end textblock             (data link) */
  89. #define CAN 0x18         /* cancel,clear eol         (control sequence) */
  90. #define SS2 0x19         /* single shift for G2 SET  (control sequence) */
  91. #define DCT 0x1a         /*                          (btx special) */
  92. #define ESC 0x1b         /* escape                     (control sequence) */
  93. #define TER 0x1c         /* terminator '#'             (btx special) */
  94. #define SS3 0x1d         /* single shift for G3 SET  (control sequence) */
  95. #define APH 0x1e         /* active position home     (control sequence) */
  96. #define US    0x1f         /* active position (x,y)     (control sequence) */
  97.  
  98. VOID IOSerial::Close(VOID)
  99. {
  100.     if(Raw)
  101.     {
  102.         delete Raw;
  103.  
  104.         Raw = NULL;
  105.     }
  106. }
  107.  
  108. LONG IOSerial::Open(CONST STRPTR Channel,ULONG Unit,ULONG Baud,BOOL RTS_CTS)
  109. {
  110.     LONG Error;
  111.  
  112.     Close();
  113.  
  114.     if(Raw = new IORawSerial)
  115.     {
  116.         if(Error = Raw->Open(Channel,Unit,Baud,RTS_CTS))
  117.         {
  118.             delete Raw;
  119.  
  120.             Raw = NULL;
  121.         }
  122.     }
  123.     else
  124.         Error = -1;
  125.  
  126.     return(Error);
  127. }
  128.  
  129. LONG IOSerial::GetChar(LONG Timeout)
  130. {
  131.     return((LONG)modeminput(Timeout));
  132. }
  133.  
  134. VOID IOSerial::PutString(CONST STRPTR String,LONG Len)
  135. {
  136.     if(Raw)
  137.     {
  138.         UBYTE *From,*s;
  139.  
  140.         if(Len < 0)
  141.             Len = strlen(String);
  142.  
  143.         From = s = (UBYTE *)String;
  144.  
  145.         while(Len > 0)
  146.         {
  147.             switch(*s)
  148.             {
  149.                 case 'Ä':
  150.  
  151.                     if(From < s)
  152.                     {
  153.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  154.  
  155.                         From = s + 1;
  156.  
  157.                         Len -= (LONG)(s - From);
  158.                     }
  159.  
  160.                     Raw->PutString((CONST STRPTR)"\0310A",2);
  161.                     break;
  162.  
  163.                 case 'ä':
  164.  
  165.                     if(From < s)
  166.                     {
  167.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  168.  
  169.                         From = s + 1;
  170.  
  171.                         Len -= (LONG)(s - From);
  172.                     }
  173.  
  174.                     Raw->PutString((CONST STRPTR)"\0310a",2);
  175.                     break;
  176.  
  177.                 case 'Ö':
  178.  
  179.                     if(From < s)
  180.                     {
  181.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  182.  
  183.                         From = s + 1;
  184.  
  185.                         Len -= (LONG)(s - From);
  186.                     }
  187.  
  188.                     Raw->PutString((CONST STRPTR)"\0310O",2);
  189.                     break;
  190.  
  191.                 case 'ö':
  192.  
  193.                     if(From < s)
  194.                     {
  195.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  196.  
  197.                         From = s + 1;
  198.  
  199.                         Len -= (LONG)(s - From);
  200.                     }
  201.  
  202.                     Raw->PutString((CONST STRPTR)"\0310o",2);
  203.                     break;
  204.  
  205.                 case 'Ü':
  206.  
  207.                     if(From < s)
  208.                     {
  209.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  210.  
  211.                         From = s + 1;
  212.  
  213.                         Len -= (LONG)(s - From);
  214.                     }
  215.  
  216.                     Raw->PutString((CONST STRPTR)"\0310U",2);
  217.                     break;
  218.  
  219.                 case 'ü':
  220.  
  221.                     if(From < s)
  222.                     {
  223.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  224.  
  225.                         From = s + 1;
  226.  
  227.                         Len -= (LONG)(s - From);
  228.                     }
  229.  
  230.                     Raw->PutString((CONST STRPTR)"\0310U",2);
  231.                     break;
  232.  
  233.                 case KEY_CursorUp:
  234.  
  235.                     if(From < s)
  236.                     {
  237.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  238.  
  239.                         From = s + 1;
  240.  
  241.                         Len -= (LONG)(s - From);
  242.                     }
  243.  
  244.                     Raw->PutChar(APU);
  245.                     break;
  246.  
  247.                 case KEY_CursorDown:
  248.  
  249.                     if(From < s)
  250.                     {
  251.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  252.  
  253.                         From = s + 1;
  254.  
  255.                         Len -= (LONG)(s - From);
  256.                     }
  257.  
  258.                     Raw->PutChar(APD);
  259.                     break;
  260.  
  261.                 case '\b':
  262.                 case 127:
  263.                 case KEY_CursorLeft:
  264.  
  265.                     if(From < s)
  266.                     {
  267.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  268.  
  269.                         From = s + 1;
  270.  
  271.                         Len -= (LONG)(s - From);
  272.                     }
  273.  
  274.                     Raw->PutChar(APB);
  275.                     break;
  276.  
  277.                 case KEY_CursorRight:
  278.  
  279.                     if(From < s)
  280.                     {
  281.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  282.  
  283.                         From = s + 1;
  284.  
  285.                         Len -= (LONG)(s - From);
  286.                     }
  287.  
  288.                     Raw->PutChar(APF);
  289.                     break;
  290.  
  291.                 case KEY_Help:
  292.  
  293.                     if(From < s)
  294.                     {
  295.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  296.  
  297.                         From = s + 1;
  298.  
  299.                         Len -= (LONG)(s - From);
  300.                     }
  301.  
  302.                     Raw->PutChar(APH);
  303.                     break;
  304.  
  305.                 case '*':
  306.  
  307.                     if(From < s)
  308.                     {
  309.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  310.  
  311.                         From = s + 1;
  312.  
  313.                         Len -= (LONG)(s - From);
  314.                     }
  315.  
  316.  
  317.                     Raw->PutChar(INI);
  318.                     break;
  319.  
  320.                 case '#':
  321.                 case '\r':
  322.                 case '\n':
  323.  
  324.                     if(From < s)
  325.                     {
  326.                         Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  327.  
  328.                         From = s + 1;
  329.  
  330.                         Len -= (LONG)(s - From);
  331.                     }
  332.  
  333.                     Raw->PutChar(TER);
  334.                     break;
  335.  
  336.                 default:
  337.  
  338.                     Len--;
  339.             }
  340.  
  341.             s++;
  342.         }
  343.  
  344.         if(From < s)
  345.             Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  346.     }
  347. }
  348.  
  349. LONG IOSerial::Waiting(VOID)
  350. {
  351.     return(buffered + Raw->Waiting());
  352. }
  353.  
  354. ULONG IOSerial::WaitMask(VOID)
  355. {
  356.     return(Raw->WaitMask());
  357. }
  358.  
  359. LONG IOSerial::getmodem(LONG Timeout)
  360. {
  361.     return(Raw->GetChar(Timeout));
  362. }
  363.  
  364. /* modeminput: this is data link layer (level 2) for getting blocks from
  365.  * btx, crc check is done and characters are send to client
  366.  */
  367.  
  368. int IOSerial::modeminput(LONG Timeout)
  369. {
  370.     LONG c1;
  371.  
  372.     if(buffered > 0)
  373.     {
  374.         buffered--;
  375.  
  376.         return((int)buffer[bufferindex++]);
  377.     }
  378.  
  379.     for(;;)
  380.     {
  381.         c1 = getmodem(Timeout);
  382.  
  383.         if(c1 < 0)
  384.             return(c1);
  385.         else
  386.             c = (UBYTE)c1;
  387.  
  388.         switch( block )
  389.         {
  390.             case TEXTBLOCK:
  391.  
  392.                 calccrc(c);
  393.  
  394.                 switch(c)
  395.                 {
  396.                     case DLE:
  397.                     case NAK:
  398.                     case ACK:
  399.                     case SOH:
  400.  
  401.                         log(("Bad char:%x\n",c1));
  402.                         break;
  403.  
  404.                     case STX:
  405.  
  406.                         if(status == ERROR || status == ETB)
  407.                         {
  408.                             crc = 0;
  409.                             bufferlen = 0;
  410.                             status = EOT;
  411.                         }
  412.  
  413.                         break;
  414.  
  415.                     case EOT:
  416.  
  417.                         ack01 = '0';
  418.                         block = NOBLOCK;
  419.                         break;
  420.  
  421.                     case ITB:
  422.                     case ETB:
  423.                     case ETX:
  424.  
  425.                         if(getcheck(Timeout) || status == ERROR)
  426.                         {
  427.                             bufferlen = 0;
  428.                             crc = 0;
  429.                             putmodem(NAK);
  430.                             status = ERROR;
  431.  
  432.                             break;
  433.                         }
  434.  
  435.                         status = c;
  436.  
  437.                         if(c == ITB)
  438.                             putmodem(ACK);
  439.                         else
  440.                         {
  441.                             ack01 ^= 1;
  442.                             putmodem(DLE);
  443.                             putmodem(ack01);
  444.  
  445.                             if(c == ETX)
  446.                                 block = NOBLOCK;  /* end of textblock */
  447.                         }
  448.  
  449.                         if(bufferlen)
  450.                         {
  451.                             buffered = bufferlen - 1;
  452.                             bufferindex = 1;
  453.  
  454.                             bufferlen = 0;
  455.  
  456.                             return((int)buffer[0]);
  457.                         }
  458.  
  459.                         break;
  460.  
  461.                     case ENQ:
  462.  
  463.                          switch( status )
  464.                         {
  465.                             case ERROR:
  466.  
  467.                                 putmodem(NAK);
  468.                                 break;
  469.  
  470.                             case EOT:
  471.  
  472.                                 putmodem(NAK);
  473.                                 break;
  474.  
  475.                             case ITB:
  476.  
  477.                                 putmodem(ACK);
  478.                                 putmodem(NAK);
  479.                                 break;
  480.  
  481.                             case ETX:
  482.                             case ETB:
  483.  
  484.                                 putmodem(DLE);
  485.                                 putmodem(ack01);
  486.                                 putmodem(NAK);
  487.                                 break;
  488.                         }
  489.  
  490.                         break;
  491.  
  492.                     default:
  493.  
  494.                         if(bufferlen < BLOCK_BUFFER_SIZE-1)
  495.                             buffer[bufferlen++] = c;
  496.                         else
  497.                             log(("Blockbuffer overflow !\n"));
  498.  
  499.                         break;
  500.                 }
  501.  
  502.                 break;
  503.  
  504.             default:      /* NOBLOCK */
  505.  
  506.                 status = EOT;
  507.  
  508.                 if(tfi)
  509.                 {
  510.                     if(tfi == SOH)
  511.                     {
  512.                         lastchar = c;
  513.                         tfi = ENQ;
  514.                     }
  515.                     else
  516.                     {
  517.                         if(c == ENQ)
  518.                             send_TFI();
  519.  
  520.                         tfi=0;
  521.                     }
  522.                 }
  523.  
  524.                 switch(c)
  525.                 {
  526.                     case EOT:
  527.  
  528.                         ack01 = '0';
  529.                         break;
  530.  
  531.                     case SOH:
  532.  
  533.                         tfi = SOH;
  534.  
  535.                     case STX:
  536.  
  537.                         crc = 0;
  538.                         block = TEXTBLOCK;
  539.                         bufferlen = 0;
  540.                         break;
  541.  
  542.                     default:
  543.  
  544.                         return((int)c);
  545.                 }
  546.  
  547.                 break;
  548.         }
  549.     }
  550. }
  551.  
  552. void IOSerial::send_TFI()
  553. {
  554.    putmodem(SOH);
  555.    putmodem('@');  /* @ = intermediate blocksize */
  556.    putmodem('5');  /* 5 = max. 256 bytes         */
  557.    putmodem(ETX);
  558. }
  559.  
  560. void IOSerial::calccrc(unsigned int c)
  561. {
  562.     register unsigned int cr = crc, ch = c;
  563.     register unsigned int i,bit;
  564.  
  565.     for(i = 0 ; i < 8 ; i++)             /* for all bits in character c */
  566.     {
  567.         bit = (cr & 1) ^ (ch & 1);
  568.  
  569.         cr >>= 1;                /* bit 15 now cleared */
  570.  
  571.         if(bit)                    /* xor for polynom: x^16+x^15+x^2+x^0 */
  572.             cr ^= 0xa001;
  573.  
  574.         ch >>= 1;                /* shift character for next bit */
  575.     }
  576.  
  577.     crc = (UWORD)cr;
  578. }
  579.  
  580. /* get 2 bytes from modem and calccrc, return value is crc (should be 0 if
  581.  * no crc error), during check handle socket inputs
  582.  */
  583. UWORD IOSerial::getcheck(LONG Timeout)
  584. {
  585.     LONG c;
  586.     int i;
  587.  
  588.     for(i = 0 ; i < 2 ; i++)
  589.     {
  590.         c = getmodem(Timeout);
  591.  
  592.         if(c >= 0)
  593.             calccrc((unsigned int)c);
  594.     }
  595.  
  596.     if(crc)
  597.         log(("CRC error %x\n",(int)crc));
  598.  
  599.     return(crc);
  600. }
  601.  
  602. /******************************************************************************/
  603.  
  604. IOSerial::IOSerial()
  605. {
  606.     Raw = NULL;
  607.  
  608.     block = NOBLOCK;
  609.     bufferlen = 0;
  610.     tfi = 0;
  611.     ack01 = '0';
  612.     status = EOT;
  613.     c = 0;
  614.     crc = 0;
  615.     lastchar = 0;
  616.     buffered = 0;
  617. }
  618.  
  619. IOSerial::~IOSerial()
  620. {
  621.     Close();
  622. }
  623.